home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 SRC / Mac / Compat / getwd.c < prev    next >
Text File  |  1995-02-17  |  4KB  |  110 lines

  1. /* Get full pathname of current working directory.  The pathname is
  2.    copied to the parameter array 'cwd', and a pointer to this array
  3.    is also returned as function result.  If an error occurred, however,
  4.    the return value is NULL but 'cwd' is filled with an error message.
  5.    
  6.    BUG: expect spectacular crashes when called from a directory whose
  7.    path would be over MAXPATH bytes long (files in such directories are
  8.    not reachable by full pathname).
  9.    
  10.    Starting with the dir ID returned by PBHGetVol, we do successive
  11.    PBGetCatInfo's to get a component of the path until we reach the
  12.    root (recognized by a dir ID of 2).  We move up along the path
  13.    using the dir ID of the parent directory returned by PBGetCatInfo.
  14.    
  15.    Then we catenate the components found in reverse order with the volume
  16.    name (already gotten from PBHGetVol), with intervening and trailing
  17.    colons
  18.    
  19.    The code works correctly on MFS disks (where it always returns the
  20.    volume name) by simply skipping the PBGetCatinfo calls in that case.
  21.    There is a 'bug' in PBGetCatInfo when called for an MFS disk (with
  22.    HFS running): it then seems to call PBHGetVInfo, which returns a
  23.    larger parameter block.  But we won't run into this problem because
  24.    we never call PBGetCatInfo for the root (assuming that PBHGetVol
  25.    still sets the root ID in this case).
  26.  
  27.    Public domain by Guido van Rossum, CWI, Amsterdam (July 1987).
  28. */
  29.  
  30. #include "macdefs.h"
  31. #if defined(MPW) || defined(__MWERKS__)
  32. #include <Strings.h>
  33. #endif
  34.  
  35. #define ROOTID 2 /* Root directory ID */
  36.  
  37. char *
  38. getwd(cwd)
  39.     char *cwd;
  40. {
  41.     /* Universal parameter block. */
  42.     union {
  43. #ifdef THINK_C
  44.         HFileInfo f;
  45.         DirInfo d;
  46.         WDPBRec w;
  47. #else /* MPW */
  48.         struct HFileInfo f;
  49.         struct DirInfo d;
  50.         struct WDPBRec w;
  51. #endif
  52.     } pb;
  53.     char buf[MAXPATH]; /* Buffer to store the name components */
  54.     char *ecwd, *ebuf; /* Pointers to end of used part of cwd and buf */
  55.     int err; /* Error code of last I/O call */
  56.     
  57.     /* First, get the default volume name and working directory ID. */
  58.     
  59.     pb.w.ioNamePtr= (unsigned char *)cwd;
  60.     err= PBHGetVol(&pb.w, FALSE);
  61.     if (err != noErr) {
  62.         sprintf(cwd, "I/O error %d in PBHGetVol", err);
  63.         return NULL;
  64.     }
  65.     ecwd= strchr((const char *)p2cstr((unsigned char*)cwd), EOS);
  66.     ebuf= buf;
  67.     *ebuf = EOS;
  68.     
  69.     /* Next, if at least we're running HFS, walk up the path. */
  70.     
  71.     if (hfsrunning()) {
  72.         long dirid= pb.w.ioWDDirID;
  73.         pb.d.ioVRefNum= pb.w.ioWDVRefNum;
  74.         while (dirid != ROOTID) {
  75.             pb.d.ioNamePtr= (unsigned char *) ++ebuf;
  76.             pb.d.ioFDirIndex= -1;
  77.             pb.d.ioDrDirID= dirid;
  78.             err= PBGetCatInfo((CInfoPBPtr)&pb.d, FALSE);
  79.             if (err != noErr) {
  80.                 sprintf(cwd, "I/O error %d in PBGetCatInfo", err);
  81.                 return NULL;
  82.             }
  83.             dirid= pb.d.ioDrParID;
  84.             ebuf += strlen((const char *)p2cstr((unsigned char *)ebuf));
  85.             /* Should check for buf overflow */
  86.         }
  87.     }
  88.     
  89.     /* Finally, reverse the list of components and append it to cwd.
  90.        Ebuf points at the EOS after last component,
  91.        and there is an EOS before the first component.
  92.        If there are no components, ebuf equals buf (but there
  93.        is still an EOS where it points).
  94.        Ecwd points at the EOS after the path built up so far,
  95.        initially the volume name.
  96.        We break out of the loop in the middle, thus
  97.        appending a colon at the end in all cases. */
  98.     
  99.     for (;;) {
  100.         *ecwd++ = ':';
  101.         if (ebuf == buf)
  102.             break;
  103.         do { } while (*--ebuf != EOS); /* Find component start */
  104.         strcpy(ecwd, ebuf+1);
  105.         ecwd= strchr(ecwd, EOS);
  106.     }
  107.     *ecwd= EOS;
  108.     return cwd;
  109. }
  110.